package com.weike.bsp.security.authentication.captcha

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.core.AuthenticationException
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.util.Assert
import java.util.*

/**
 * An [AuthenticationProvider] implementation that retrieves user details from a
 * [UserDetailsService].
 *
 *
 * 参考 [DaoAuthenticationProvider]
 *
 * {username, captcha, password} 验证
 *
 * @author tiger
 */
//@Component
class CaptchaAuthenticationProvider(
        private var captchaDetailsService: CaptchaDetailsService?
) : DaoAuthenticationProvider() {

    override fun doAfterPropertiesSet() {
        super.doAfterPropertiesSet()
        Assert.notNull(captchaDetailsService, "A CaptchaDetailsService must be set")
    }

    @Throws(AuthenticationException::class)
    override fun additionalAuthenticationChecks(userDetails: UserDetails, authentication: UsernamePasswordAuthenticationToken) {
        if (authentication is CaptchaAuthenticationToken) {
            checkCaptcha(authentication)
            super.additionalAuthenticationChecks(userDetails, authentication)
        } else {
            super.additionalAuthenticationChecks(userDetails, authentication)
        }
    }

    /**
     * 验证验证码
     *
     * @param c 验证码信息
     */
    private fun checkCaptcha(c: CaptchaAuthenticationToken) {
        // 验证token
        if (c.captureCode == null) {
            throw BadCaptchaException("验证码不可为空")
        }

        val rawCaptcha = captchaDetailsService?.loadCaptchaByUsername(c.name)

        if (!Objects.equals(rawCaptcha, c.captureCode)) {
            throw BadCaptchaException("验证码错误")
        }
    }

    companion object {
        const val IMAGE_CODE_KEY = "imageCodeKey"
    }
}
